#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "MSTK.h"
#include <mpi.h>

int main(int argc, char *argv[]) {
  int i, j, idx, ok, dim;
  char mname[256],filename[256];
  char buf[256], attname[256];
  char subfilename[256];
  Mesh_ptr mesh, recv_mesh, *submeshes;
  RepType rtype;
  /* default divide into two parts */
  int num = 2;
  int rank;
  double dt, T;
  MVertex_ptr mv;
  /* Initialize MSTK - Always do this even if it does not seem to
     matter in this version of MSTK */
  MSTK_Init();  
  /* command line parameter */
  MPI_Init(&argc,&argv);
  MPI_Comm_size(MPI_COMM_WORLD,&num);
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
  
  /* Load the mesh */
  strcpy(mname,argv[1]);
  strcpy(filename,mname);
  strcat(filename,".mstk");
  dim = atoi(argv[3]);    
  /* master process read in and divide the mesh */
  if(rank == 0) { 
    mesh = MESH_New(UNKNOWN_REP);
    ok = MESH_InitFromFile(mesh,filename);
    if (!ok) {
      fprintf(stderr,"Cannot open input file %s\n\n\n",filename);
      exit(-1);
    }
    fprintf(stdout,"mstk mesh %s read in successfully\n",filename);

    MAttrib_ptr attrib;
    strcpy(attname,"indicater");
    attrib = MAttrib_New(mesh,attname,INT,MVERTEX);
   
    idx = 0;
    while(mv = MESH_Next_Vertex(mesh,&idx)) 
      MEnt_Set_AttVal(mv,attrib,0,0,NULL);      
    /* Partition the mesh*/
   
    rtype = MESH_RepType(mesh);
    submeshes = (Mesh_ptr *)MSTK_malloc((num)*sizeof(Mesh_ptr));
    ok = MSTK_Mesh_Partition(mesh,submeshes,num,1,1);
    fprintf(stdout,"%s has been partitioned into %d submeshes\n",filename,num);

    /* send mesh */
    for(i = 1; i < num; i++) {
      MESH_SendMesh(submeshes[i],i,MPI_COMM_WORLD);
      MESH_SendAttr(submeshes[i],0,i,MPI_COMM_WORLD);
    }
  }

  /* receive mesh */
  if(rank == 0) {
    /* submesh on the root */
    recv_mesh = submeshes[0];
    MESH_CopyAttr(mesh,recv_mesh,0);
  }
  else {
    recv_mesh = MESH_New(UNKNOWN_REP);
    MESH_RecvMesh(recv_mesh,dim,0,rank,MPI_COMM_WORLD);
    MESH_RecvAttr(recv_mesh,0,0,rank,MPI_COMM_WORLD);
    fprintf(stdout,"submesh %d received\n",rank);
  }

  /* build ghost list */
  MESH_BuildGhostList(recv_mesh);


  /* update ghost info */
  MESH_UpdateGlobalInfo(recv_mesh, rank, num,  MPI_COMM_WORLD);  
  MPI_Barrier(MPI_COMM_WORLD);
  T = MPI_Wtime();
  /* do some operation on attributes */
  /* update FacePtype to be face global id */
  idx = 0;
  while(mv = MESH_Next_Vertex(recv_mesh,&idx)) {
    for(j = 0; j < 5000; j++)
      ;
  }
  MESH_UpdateAttr(recv_mesh,0,rank,num,MPI_COMM_WORLD);
  printf("time %lf on rank %d\n",MPI_Wtime()-T,rank);

  MPI_Finalize();
  return 1;
}

